#include "Battle.h"

#define kTagBackground 0
#define kTagGame 100
#define kTagInfo 200
#define kTagMenu 1000

#define kTagPhysicsDebug 1
#define kTagAir 2
#define kTagExplore 10

#define kGroupMy 1
#define kGroupEnemy 2
#define kLayerMyAir 1
#define kLayerMyBullet 2
#define kLayerEnemy 4
#define kLayerEnemyBullet 8
#define kLayerEnemyMissile 16
#define kLayerWall 1024

BattleLayer::BattleLayer()
{
	fireTime = 0;
}

BattleLayer::~BattleLayer()
{
	for (int i = 0; i < 4; i++)
	{
		cpShapeFree(walls[i]);
	}
	cpSpaceFree(space);
}

Battle::Battle(void)
{
}

bool BattleLayer::init(){
	if(!CCLayer::init()){
		return false;
	}
	CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false);
	CCSize size = CCDirector::sharedDirector()->getVisibleSize();
	GCpShapeCache::sharedShapeCache()->addShapesWithFile("battlePE.plist");
	W = size.width;
	H = size.height;

	CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("battle.plist");
	CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("explore.plist");
	SimpleAudioEngine::sharedEngine()->preloadEffect("explore.mp3");

	space = cpSpaceNew();
	space->gravity = cpv(0,0);

	pDebugNode = CCPhysicsDebugNode::create(space);
	addChild(pDebugNode,kTagPhysicsDebug);
	airParent = CCSpriteBatchNode::create("battle.png");
	addChild(airParent,kTagAir,kTagAir);

	initWalls();

	addMyAirAtPos(ccp(W/2,H/4));

	cpSpaceAddCollisionHandler(space,kLayerWall,kLayerMyBullet,cpOnCollisionWall,NULL,NULL,NULL,NULL);
	cpSpaceAddCollisionHandler(space,kLayerWall,kLayerEnemy,cpOnCollisionWall,NULL,NULL,NULL,NULL);
	cpSpaceAddCollisionHandler(space,kLayerMyBullet,kLayerEnemy,cpOnShootCollision,NULL,NULL,NULL,NULL);
	scheduleUpdate();
	return true;
}
cpBool BattleLayer::cpOnCollisionWall(cpArbiter *arb, cpSpace *space, void *data){
	CP_ARBITER_GET_SHAPES(arb,a,b);
	cpShape* shape = b;
	cpSpaceAddPostStepCallback(space,onStepOverRemove,shape,NULL);
	return false;
}

void BattleLayer::onStepOverRemove(cpSpace *space, void *key, void *data){
	cpShape* shape = (cpShape*)key;
	cpBody* body = shape->body;
	CCSprite* sprite = (CCSprite*)(body->data);
	if(data){
		showExplore(sprite->getPosition(),sprite->getParent()->getParent());
	}
	cpSpaceRemoveShape(space,shape);
	cpSpaceRemoveBody(space,body);
	cpShapeFree(shape);
	cpBodyFree(body);
	sprite->removeFromParentAndCleanup(true);
}

cpBool BattleLayer::cpOnShootCollision(cpArbiter *arb, cpSpace *space, void *data){
	CP_ARBITER_GET_SHAPES(arb,a,b);
	cpSpaceAddPostStepCallback(space,onStepOverRemove,a,NULL);
	cpSpaceAddPostStepCallback(space,onStepOverRemove,b,b);
	return false;
}

void BattleLayer::addMyAirAtPos(const CCPoint& p){
	cpBody* body = GCpShapeCache::sharedShapeCache()->createBodyWithName("myAir",space,kLayerMyAir,kGroupMy,kLayerMyAir);
	body->p = cpv(p.x,p.y);
	CCPhysicsSprite* sprite = CCPhysicsSprite::createWithSpriteFrameName("myAir.png");
	airParent->addChild(sprite);
	sprite->setCPBody(body);
	sprite->setPosition(p);
	body->data = sprite;
	player = body;
	playerSp = sprite;
}
void BattleLayer::addMyBulletAtPos(const CCPoint& p){
	cpBody* body = cpBodyNew(1,1);
	body->p = cpv(p.x,p.y);
	cpSpaceAddBody(space,body);
	cpShape* shape = cpBoxShapeNew(body,11,70);
	cpSpaceAddShape(space,shape);
	shape->group = kGroupMy;
	shape->layers = kLayerMyBullet | kLayerEnemy;
	shape->collision_type = kLayerMyBullet;
	CCPhysicsSprite* sprite = CCPhysicsSprite::createWithSpriteFrameName("mybullet.png");
	airParent->addChild(sprite);
	sprite->setCPBody(body);
	sprite->setPosition(p);
	body->data = sprite;
	body->v = cpv(0,1000);
}
void BattleLayer::addEnemyAtPos(const CCPoint& p){
	int num = 4;
	cpVect vects[]={cpv(-14,9),cpv(0,22),cpv(14,9),cpv(0,-24)};
	cpBody* body = cpBodyNew(100,cpMomentForPoly(1,num,vects,cpvzero));
	body->p = cpv(p.x,p.y);
	cpSpaceAddBody(space,body);
	cpShape* shape = cpPolyShapeNew(body,num,vects,cpvzero);
	cpSpaceAddShape(space,shape);
	shape->group = kGroupEnemy;
	shape->layers = kLayerEnemy | kLayerMyBullet;
	shape->collision_type = kLayerEnemy;
	CCPhysicsSprite* sprite = CCPhysicsSprite::createWithSpriteFrameName("enemy.png");
	airParent->addChild(sprite);
	sprite->setCPBody(body);
	sprite->setPosition(p);
	body->data = sprite;
	body->v = cpv(CCRANDOM_0_1()*100-50,-CCRANDOM_0_1()*100-100);
}
void BattleLayer::initWalls(){
	walls[0] = cpBoxShapeNew2(space->staticBody,cpBBNew(-60,-60,-50,H+60));
	walls[1] = cpBoxShapeNew2(space->staticBody,cpBBNew(-60,-60,W+60,-50));
	walls[2] = cpBoxShapeNew2(space->staticBody,cpBBNew(W+50,-60,W+60,H+60));
	walls[3] = cpBoxShapeNew2(space->staticBody,cpBBNew(-60,H+50,W+60,H+60));
	for( int i=0;i<4;i++) {
		walls[i]->e = 1.0f;
		walls[i]->u = 1.0f;
		walls[i]->layers = CP_ALL_LAYERS;
		walls[i]->collision_type = kLayerWall;
		cpSpaceAddStaticShape(space, walls[i] );
	}
}

void BattleLayer::update(float delta){
	int steps = 2;
	float dt = CCDirector::sharedDirector()->getAnimationInterval()/(float)steps;

	for(int i=0; i<steps; i++){
		cpSpaceStep(space, dt);
	}
	fireTime+=delta;
	if(fireTime>0.2){
		fireTime=0;
		fire();
	}
	if(CCRANDOM_0_1()<0.03){
		addEnemyAtPos(ccp(CCRANDOM_0_1()*W,H));
	}
}
void BattleLayer::fire(){
	addMyBulletAtPos(playerSp->getPosition());
}
bool BattleLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
	return true;
}
void BattleLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent){
	CCPoint delta = pTouch->getDelta();
	cpBodySetPos(player,cpvadd(player->p,cpv(delta.x,delta.y)));
}

CCSprite* BattleLayer::showExplore(const CCPoint& p,CCNode* parent){
	CCArray* arr = CCArray::createWithCapacity(39);
	char str[100] = {0};
	CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();
	for(int i = 0 ;i <= 19 ;i++){
		sprintf(str,"explore%04d.png",i);
		CCSpriteFrame* frame = cache->spriteFrameByName(str);
		arr->addObject(frame);
	}
	CCAnimation* animation = CCAnimation::createWithSpriteFrames(arr,0.033f);
	CCAnimate* anim = CCAnimate::create(animation);
	CCSprite* sp = CCSprite::create();
	sp->setPosition(p);
	parent->addChild(sp,kTagExplore,kTagExplore);
	CCCallFuncN* animOverCallback = CCCallFuncN::create(parent,callfuncN_selector(BattleLayer::removeSelf));
	sp->runAction(CCSequence::create(anim,animOverCallback,NULL));
	SimpleAudioEngine::sharedEngine()->playEffect("explore.mp3",false);
	return sp;
}
void BattleLayer::removeSelf(CCNode* node){
	node->removeFromParentAndCleanup(true);
}

/************************************************************************/
/* Battle                                                                     */
/************************************************************************/
Battle::~Battle(void)
{
}

bool Battle::init(){
	if(!CCScene::init()){
		return false;
	}
	BattleLayer* gameLayer = BattleLayer::create();
	addChild(gameLayer,kTagGame,kTagGame);

	return true;
}
